using System;
using DevExpress.Xpo;
using SmartPeople.Framework.SecuritySpace;
using SmartPeople.Framework.SecuritySpace;

namespace SmartPeople.Framework.Security.Providers.XPO
{
    [Persistent("SecurityUser")]
    internal class XPSecurityUser : XPCustomObject, ISecurityUser
    {
        public XPSecurityUser()
        {
        }

        public XPSecurityUser(Session session) : base(session)
        {
            // This constructor is used when an object is loaded from a persistent storage.
            // Do not place any code here.
        }

        #region Old Constructors

        //public XPSecurityUser(string userName, string password, string email)
        //{
        //    //gID = Guid.NewGuid();
        //    this.userName = userName;
        //    this.password = password;
        //    this.email = email;
        //    creationDate = DateTime.Now;
        //}


        //public XPSecurityUser(string userName, string password, string email, string passwordQuestion,
        //                      string passwordAnswer)
        //    : this(userName, password, email)
        //{
        //    this.passwordQuestion = passwordQuestion;
        //    this.passwordAnswer = passwordAnswer;
        //    this.email = email;
        //} 

        #endregion

        #region Fields

        [Key(AutoGenerate = true)]
        [Persistent("GID")]
        private Guid gID;

        [Persistent("FullName")]
        private string fullName;

        [NullValue("NULL")]
        [Indexed(Unique = true)]
        [Persistent("Email")]
        private string email;

        [Persistent("Description")]
        private string description;

        [Indexed(Unique = true)]
        [Persistent("UserName")]
        private string userName;

        [Persistent("Password")]
        private string password;

        [Persistent("PasswordQuestion")]
        private string passwordQuestion;

        [Persistent("PasswordAnswer")]
        private string passwordAnswer;

        [Persistent("SessionID")]
        private Guid sessionID;

        [Persistent("LastActivityDate")]
        private DateTime lastActivityDate;

        [Persistent("Comment")]
        private string comment;

        [Persistent("IsApproved")]
        private bool isApproved;

        [Persistent("IsLockedOut")]
        private bool isLockedOut;

        [Persistent("IsOnline")]
        private bool isOnline;

        [Persistent("LastLockoutDate")]
        private DateTime lastLockoutDate;

        [Persistent("LastLoginDate")]
        private DateTime lastLoginDate;

        [Persistent("LastPasswordChangedDate")]
        private DateTime lastPasswordChangedDate;

        private string providerName;

        private object providerUserKey;

        private string type;

        [Persistent("CreationDate")]
        private DateTime creationDate;

        [Persistent("UserToken")]
        private Guid userToken;

        [Persistent("IsReadOnly")]
        private bool isReadOnly;

        #endregion

        #region Properties

        [NonPersistent]
        public Guid UserToken
        {
            get { return userToken; }
            set
            {
                if (userToken != value)
                {
                    Guid OldValue = userToken;
                    userToken = value;
                    OnChanged("UserToken", OldValue, value);
                }
            }
        }


        [NonPersistent]
        public Guid GID
        {
            get { return gID; }
            set
            {
                if (gID != value)
                {
                    Guid OldValue = gID;
                    gID = value;
                    OnChanged("GID", OldValue, value);
                }
            }
        }

        [NonPersistent]
        public string UserName
        {
            get { return userName; }
            set
            {
                if (userName != value)
                {
                    string OldValue = userName;
                    userName = value;
                    OnChanged("UserName", OldValue, value);
                }
            }
        }

        //was private
        [NonPersistent]
        public string Password
        {
            get { return password; }
            set
            {
                if (password != value)
                {
                    string OldValue = password;
                    password = value;
                    OnChanged("Password", OldValue, value);
                }
            }
        }

        [NonPersistent]
        public Guid SessionID
        {
            get { return sessionID; }
            set
            {
                if (sessionID != value)
                {
                    Guid OldValue = sessionID;
                    sessionID = value;
                    OnChanged("SessionID", OldValue, value);
                }
            }
        }

        [NonPersistent]
        public bool IsReadOnly
        {
            get { return isReadOnly; }
            set
            {
                // The old value of the Name property.
                bool oldValue = isReadOnly;
                if (oldValue == value)
                    return;
                isReadOnly = value;
                // Keep track of every change made to the Name property.
                OnChanged("IsReadOnly", oldValue, value);
            }
        }



        [NonPersistent]
        public string FullName
        {
            get { return fullName; }
            set
            {
                // The old value of the Name property.
                string oldValue = fullName;
                if (oldValue == value)
                    return;
                fullName = value;
                // Keep track of every change made to the Name property.
                OnChanged("FullName", oldValue, value);
            }
        }

        [NonPersistent]
        public string Email
        {
            get { return email; }
            set
            {
                // The old value of the Name property.
                string oldValue = email;
                if (oldValue == value)
                    return;
                email = value;
                // Keep track of every change made to the Name property.
                OnChanged("Email", oldValue, value);
            }
        }

        [NonPersistent]
        public string Description
        {
            get { return description; }
            set
            {
                // The old value of the Name property.
                string oldValue = description;
                if (oldValue == value)
                    return;
                description = value;
                // Keep track of every change made to the Name property.
                OnChanged("Description", oldValue, value);
            }
        }

        [NonPersistent]
        public string Type
        {
            get { return type; }
            set
            {
                // The old value of the Name property.
                string oldValue = type;
                if (oldValue == value)
                    return;
                type = value;
                // Keep track of every change made to the Name property.
                OnChanged("Type", oldValue, value);
            }
        }

        [NonPersistent]
        public string Comment
        {
            get { return comment; }
            set
            {
                // The old value of the Name property.
                string oldValue = comment;
                if (oldValue == value)
                    return;
                comment = value;
                // Keep track of every change made to the Name property.
                OnChanged("Comment", oldValue, value);
            }
        }

        [NonPersistent]
        public DateTime CreationDate
        {
            get { return creationDate; }
            set
            {
                // The old value of the Name property.
                DateTime oldValue = creationDate;
                if (oldValue == value)
                    return;
                creationDate = value;
                // Keep track of every change made to the Name property.
                OnChanged("CreationDate", oldValue, value);
            }
        }


        [NonPersistent]
        public bool IsApproved
        {
            get { return isApproved; }
            set
            {
                // The old value of the Name property.
                bool oldValue = isApproved;
                if (Equals(oldValue, value))
                    return;
                isApproved = value;
                // Keep track of every change made to the Name property.
                OnChanged("IsApproved", oldValue, value);
            }
        }

        [NonPersistent]
        public bool IsLockedOut
        {
            get { return isLockedOut; }
            set
            {
                // The old value of the Name property.
                bool oldValue = isLockedOut;
                if (Equals(oldValue, value))
                    return;
                isLockedOut = value;
                // Keep track of every change made to the Name property.
                OnChanged("IsLockedOut", oldValue, value);
            }
        }

        [NonPersistent]
        public bool IsOnline
        {
            get { return isOnline; }
            set
            {
                // The old value of the Name property.
                bool oldValue = isOnline;
                if (Equals(oldValue, value))
                    return;
                isOnline = value;
                // Keep track of every change made to the Name property.
                OnChanged("IsOnline", oldValue, value);
            }
        }

        [NonPersistent]
        public DateTime LastActivityDate
        {
            get { return lastActivityDate; }
            set
            {
                // The old value of the Name property.
                DateTime oldValue = lastActivityDate;
                if (oldValue == value)
                    return;
                lastActivityDate = value;
                // Keep track of every change made to the Name property.
                OnChanged("LastActivityDate", oldValue, value);
            }
        }

        [NonPersistent]
        public DateTime LastLockoutDate
        {
            get { return lastLockoutDate; }
            set
            {
                // The old value of the Name property.
                DateTime oldValue = lastLockoutDate;
                if (Equals(oldValue, value))
                    return;
                lastLockoutDate = value;
                // Keep track of every change made to the Name property.
                OnChanged("LastLockoutDate", oldValue, value);
            }
        }

        [NonPersistent]
        public DateTime LastLoginDate
        {
            get { return lastLoginDate; }
            set
            {
                // The old value of the Name property.
                DateTime oldValue = lastLoginDate;
                if (oldValue == value)
                    return;
                lastLoginDate = value;
                // Keep track of every change made to the Name property.
                OnChanged("LastLoginDate", oldValue, value);
            }
        }

        [NonPersistent]
        public DateTime LastPasswordChangedDate
        {
            get { return lastPasswordChangedDate; }
            set
            {
                // The old value of the Name property.
                DateTime oldValue = lastPasswordChangedDate;
                if (Equals(oldValue, value))
                    return;
                lastPasswordChangedDate = value;
                // Keep track of every change made to the Name property.
                OnChanged("LastPasswordChangedDate", oldValue, value);
            }
        }

        [NonPersistent]
        public string PasswordQuestion
        {
            get { return passwordQuestion; }
            set
            {
                string oldValue = passwordQuestion;
                if (Equals(oldValue, value))
                    return;
                passwordQuestion = value;
                // Keep track of every change made to the Name property.
                OnChanged("PasswordQuestion", oldValue, value);
            }
        }

        [NonPersistent]
        public string PasswordAnswer
        {
            get { return passwordAnswer; }
            set
            {
                // The old value of the Name property.
                string oldValue = passwordAnswer;
                if (Equals(oldValue, value))
                    return;
                passwordAnswer = value;
                // Keep track of every change made to the Name property.
                OnChanged("PasswordAnswer", oldValue, value);
            }
        }


        [NonPersistent]
        public string ProviderName
        {
            get { return providerName; }
            set
            {
                // The old value of the Name property.
                string oldValue = providerName;
                if (Equals(oldValue, value))
                    return;
                providerName = value;
                // Keep track of every change made to the Name property.
                OnChanged("ProviderName", oldValue, value);
            }
        }

        [NonPersistent]
        public object ProviderUserKey
        {
            get { return providerUserKey; }
            set
            {
                // The old value of the Name property.
                object oldValue = providerUserKey;
                if (Equals(oldValue, value))
                    return;
                providerUserKey = value;
                // Keep track of every change made to the Name property.
                OnChanged("ProviderUserKey", oldValue, value);
            }
        }

        [Association("SecurityRoleUsers", typeof (XPSecurityRole), UseAssociationNameAsIntermediateTableName = true)]
        internal XPCollection<XPSecurityRole> Roles
        {
            get { return GetCollection<XPSecurityRole>("Roles"); }
        }

        #endregion

        #region ChangePassword(string oldPassword, string newPassword)

        public bool ChangePassword(string oldPassword, string newPassword)
        {
            if (oldPassword != GetPassword())
            {
                throw new ArgumentException("Old password entered is not valid!", GetType().FullName);
            }
            password = newPassword;
            lastPasswordChangedDate = DateTime.Now;
            Save();
            return true;
        }

        #endregion

        #region ChangePasswordQuestionAndAnswer(string password, string newPasswordQuestion,string newPasswordAnswer)

        public bool ChangePasswordQuestionAndAnswer(string password, string newPasswordQuestion,
                                                    string newPasswordAnswer)
        {
            if (String.IsNullOrEmpty(password))
                throw new ArgumentNullException("Password cannot be empty or null!");

            if (String.IsNullOrEmpty(newPasswordQuestion))
                throw new ArgumentNullException("New password question cannot be empty or null!");

            if (String.IsNullOrEmpty(newPasswordAnswer))
                throw new ArgumentNullException("New password answer cannot be empty or null!");

            this.password = password;
            passwordQuestion = newPasswordQuestion;
            passwordAnswer = newPasswordAnswer;
            lastPasswordChangedDate = DateTime.Now;
            Save();
            return true;
        }

        #endregion

        #region GetPassword

        public string GetPassword()
        {
            return password;
        }

        #endregion

        #region GetPassword(string passwordAnswer)

        public string GetPassword(string passwordAnswer)
        {
            if (PasswordAnswer != passwordAnswer)
                throw new ArgumentException("Pasword answer is incorrect!");
            return password;
        }

        #endregion


   


        #region ResetPassword

        /// <summary>
        /// Resets a user's password to a new, automatically generated password.
        /// </summary>
        /// <returns>
        /// The new password for the membership user.
        /// </returns>
        /// <remarks>
        /// </remarks>
        public string ResetPassword()
        {
            Password = SecurityPolicy.GeneratePassword();
            lastPasswordChangedDate = DateTime.Now;
            Save();
            return password;
        }





        #endregion

        #region ResetPassword

        public string ResetPassword(string passwordAnswer)
        {
            if (PasswordAnswer != passwordAnswer)
                throw new ArgumentException("Password answer is not correct!");

            return ResetPassword();
        }

        #endregion

        #region UnlockUser

        public bool UnlockUser()
        {
            if (IsLockedOut == true)
            {
                IsLockedOut = false;
                return true;
            }
            return false;
        }

        #endregion

        #region MembershipUser unused

        /*
        private MembershipUser membershipUser;

        protected internal XPSecurityUser(MembershipUser membershipUser)
        {
            this.membershipUser = membershipUser;
        }

        public XPSecurityUser(
            string providerName,
            string name,
            object providerUserKey,
            string email,
            string passwordQuestion,
            string comment,
            bool isApproved,
            bool isLockedOut,
            DateTime creationDate,
            DateTime lastLoginDate,
            DateTime lastActivityDate,
            DateTime lastPasswordChangedDate,
            DateTime lastLockoutDate)
        {
            membershipUser =
                new MembershipUser(
                    providerName,
                    name,
                    providerUserKey,
                    email,
                    passwordQuestion,
                    comment,
                    isApproved,
                    isLockedOut,
                    creationDate,
                    lastLoginDate,
                    lastActivityDate,
                    lastPasswordChangedDate,
                    lastLockoutDate);
        }

        protected internal MembershipUser MembershipUser
        {
            get
            {
                return membershipUser;
            }
            set
            {
                membershipUser = value;
            }
        }
        */

        #region ISecurityUser Members

        /*
		string ISecurityUser.Comment
		{
			get
			{
				return membershipUser.Comment;
			}
			set
			{
				membershipUser.Comment = value;
			}
		}

		DateTime ISecurityUser.CreationDate
		{
			get
			{
				return membershipUser.CreationDate;
			}
		}

		string ISecurityUser.Email
		{
			get
			{
				return membershipUser.Email;
			}
			set
			{
				membershipUser.Email = value;
			}
		}

		bool ISecurityUser.IsApproved
		{
			get
			{
				return membershipUser.IsApproved;
			}
			set
			{
				membershipUser.IsApproved = value;
			}
		}

		bool ISecurityUser.IsLockedOut
		{
			get
			{
				return membershipUser.IsLockedOut;
			}
		}

		bool ISecurityUser.IsOnline
		{
			get
			{
				return membershipUser.IsOnline;
			}
		}

		DateTime ISecurityUser.LastActivityDate
		{
			get
			{
				return membershipUser.LastActivityDate;
			}
			set
			{
				membershipUser.LastActivityDate = value;
			}
		}

		DateTime ISecurityUser.LastLockoutDate
		{
			get
			{
				return membershipUser.LastLockoutDate;
			}
		}

		DateTime ISecurityUser.LastLoginDate
		{
			get
			{
				return membershipUser.LastLoginDate;
			}
			set
			{
				membershipUser.LastLoginDate = value;
			}
		}

		DateTime ISecurityUser.LastPasswordChangedDate
		{
			get
			{
				return membershipUser.LastPasswordChangedDate;
			}
		}

		string ISecurityUser.PasswordQuestion
		{
			get
			{
				return membershipUser.PasswordQuestion;
			}
		}

		string ISecurityUser.ProviderName
		{
			get
			{
				return membershipUser.ProviderName;
			}
		}

		object ISecurityUser.ProviderUserKey
		{
			get
			{
				return membershipUser.ProviderUserKey;
			}
		}

		string ISecurityUser.UserName
		{
			get
			{
				return membershipUser.UserName;
			}
		}

		bool ISecurityUser.ChangePassword(string oldPassword, string newPassword)
		{
			return membershipUser.ChangePassword(oldPassword, newPassword);
		}

		bool ISecurityUser.ChangePasswordQuestionAndAnswer(string password, string newPasswordQuestion, string newPasswordAnswer)
		{
			return membershipUser.ChangePasswordQuestionAndAnswer(password, newPasswordQuestion, newPasswordAnswer);
		}

		string ISecurityUser.GetPassword()
		{
			return membershipUser.GetPassword();
		}

		string ISecurityUser.GetPassword(string passwordAnswer)
		{
			return membershipUser.GetPassword(passwordAnswer);
		}

		string ISecurityUser.ResetPassword()
		{
			return membershipUser.ResetPassword();
		}

		string ISecurityUser.ResetPassword(string passwordAnswer)
		{
			return membershipUser.ResetPassword(passwordAnswer);
		}

		bool ISecurityUser.UnlockUser()
		{
			return membershipUser.UnlockUser();
		}
        */

        #endregion

        #endregion
    }
}